Refactor nix/lib.nix and cache hatter for iOS/watchOS#215
Merged
jappeace merged 9 commits intojappeace:developfrom Apr 26, 2026
Merged
Refactor nix/lib.nix and cache hatter for iOS/watchOS#215jappeace merged 9 commits intojappeace:developfrom
jappeace merged 9 commits intojappeace:developfrom
Conversation
Eliminate every fromIntegral call (70+) across 20 files by using explicit unwitch conversion functions. This makes numeric type conversions self-documenting and catches unsafe casts at compile time. Conversion patterns used: - Int32 ↔ CInt: Int32.toCInt / CInt.toInt32 (total) - CInt → Int: CInt.toInt (total, for IntMap keys and BS lengths) - Int → CInt: Int.toCInt with maybe 0 id (partial) - Int → Word8: Int.toWord8 with maybe 0 id (partial, hex parsing) - Word8 → Int/Double: Word8.toInt / Word8.toDouble (total) - Int32 → Int (IntMap keys): CInt.toInt . Int32.toCInt (total chain, avoids Int32.toInt which returns Maybe due to Haskell spec) - Int32/CInt → Double: Int32.toDouble / CInt.toDouble (total) Added unwitch 2.2.0 to cabal deps (library, test-suite, redraw-demo) and to both nix overlays (hpkgs.nix for native, cross-deps.nix for Android cross-compilation). Prompt: replace all primitive conversions in hatter with unwitch Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
iOS and watchOS use ios-deps.nix (native macOS GHC) rather than cross-deps.nix (Android cross-GHC). The unwitch package was missing from the iOS/watchOS haskellPackages overlay, causing "Could not find module Unwitch.Convert.*" errors in CI. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
mkIOSLib compiles hatter with raw ghc -staticlib, not through cabal, so its non-boot dependencies must be explicitly provided in the crossDeps package DB. Before unwitch, hatter only used GHC boot packages (base, containers, text, etc.). Now it also needs unwitch. Add hatterOwnDeps list to ios-deps.nix so the unwitch .a/.hi/.conf are collected even when no consumerCabalFile is provided (as in CI). This fixes iOS and watchOS builds which both use ios-deps.nix. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
collect-deps.nix only processes packages explicitly in its deps list — it doesn't follow propagatedBuildInputs. Since hatter's .conf now references unwitch, unwitch's .a and .conf must also be collected. Without this, Android builds fail with "unusable due to missing dependencies: unwitch-2.2.0-..." when importing Hatter. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Categorise all changes since 0.2.0 into Breaking changes, Added, and Fixed sections based on the git history (c17518a..HEAD). Prompt: go repair the changelog in hatter for 0.3.0, use git to figure out what happened between the 0.3.0 release and 0.2.0 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace placeholder 0.3.0 changelog with detailed release notes
unwitch 3.0.0 makes Int32.toInt total (Int32 -> Int) on GHC, so the int32ToIntKey helper and CInt.toInt . Int32.toCInt chain are no longer needed. Replace all 10 copies with direct Int32.toInt calls and remove the CInt import from files that only used it for the helper. Bump unwitch dependency to >= 3.0.0, point nix overlays to the jappeace/unwitch commit with the total conversion. Prompt: go simplify conversions here with unwitch 3 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace all fromIntegral with unwitch conversions
Combines two improvements to the Nix build infrastructure:
1. Deduplicate nix/lib.nix (995 → ~700 lines, 30% reduction):
- Extract shared data lists (modules, C sources, headers, symbols)
and helper functions into top-level let bindings
- Merge mkIOSLib + mkWatchOSLib into internal mkAppleStaticLib
parameterised by platform; public API preserved via thin wrappers
- Merge mkSimulatorApp + mkWatchOSSimulatorApp into internal
mkAppleSimulatorApp; public API preserved
- Replace 14 repetitive NDK compile blocks with map over list
- Hoist applePkgs, appleGhc, gmpStatic, libffiStatic to top-level
2. Build hatter as a cached cabal package for iOS/watchOS:
- ios-deps.nix: add hatterSrc param, build hatter via callCabal2nix
so the .a and package DB entry are cached
- ios.nix, watchos.nix: pass hatterSrc to ios-deps.nix
- mkAppleStaticLib: when crossDeps is provided, only compile
Main.hs + run_main.c instead of all 22 modules + 19 C sources
- Standalone fallback (crossDeps == null) preserved
Adding a new bridge module now means editing 1 list, not 6+ places.
Demo apps and consumers only recompile their entry point.
Prompt: combine PR jappeace#213 and jappeace#214 into a single PR
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This was referenced Apr 21, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
mkAppleStaticLib, merge simulator functions, replace 14 repetitive NDK blocks withmap— 995 → ~700 lines (30% reduction)callCabal2nixpackage so.aand package DB are cachedcrossDepsis provided, only compileMain.hs+run_main.cinstead of all 22 modules + 19 C sourcesSupersedes #213 and #214.
Test plan
nix-instantiate --parsepasses on all modified filesnix-instantiate --evalconfirms all 6 public functions exported🤖 Generated with Claude Code